home *** CD-ROM | disk | FTP | other *** search
- (*===========================================================================*)
- (* X/Ymodem Protocol processor -- Download *)
- (* *)
- (* Copyright 1989 by H. Roy Engehausen. All rights reserved. *)
- (* This software may be freely distributed AND used, but it may not *)
- (* under any circumstances be sold by anyone other than the author. *)
- (* It may be distributed by a commercial company as long as it is *)
- (* FOR no cost. *)
- (* *)
- (*===========================================================================*)
-
- PROCEDURE xy_download(end_it : BOOLEAN);
-
- VAR
-
- b : BOOLEAN;
- err_count : BYTE;
- i : WORD;
- s : STRING[10];
-
- CONST
- debug = FALSE;
-
- (*-------------------------------------------------------------------------*)
- (* Subroutine to send an abort *)
- (*-------------------------------------------------------------------------*)
-
- PROCEDURE send_abort;
-
- VAR
- i : BYTE;
-
- BEGIN;
-
- FOR i := 1 TO 10 DO
- send_tnc_data_str(can);
- send_drain;
-
- FOR i := 1 TO 50 DO
- task_switch;
-
- do_mess_local(message_bin_abort_out);
- abort_sw := TRUE;
-
- END;
-
- (*-------------------------------------------------------------------------*)
- (* Subroutine to prep the buffer *)
- (*-------------------------------------------------------------------------*)
-
- PROCEDURE prep_buff;
-
- BEGIN;
-
- (*---------------------------------------------------------------------*)
- (* Build the block number *)
- (*---------------------------------------------------------------------*)
-
- big_buff^.xy_b_no := block_no;
- big_buff^.xy_b_no_invert := NOT block_no;
-
- (*---------------------------------------------------------------------*)
- (* Build the check characters *)
- (*---------------------------------------------------------------------*)
-
- IF crc_sw THEN
- BEGIN;
- build_crc;
- tail_ptr^.xy_crc_hi := HI(check_num);
- tail_ptr^.xy_crc_lo := LO(check_num);
- INC(b_size);
- END
- ELSE
- BEGIN;
- build_sum;
- tail_ptr^.xy_chksum := check_num;
- END;
-
- END;
-
- (*-------------------------------------------------------------------------*)
- (* Subroutine to send the buffer *)
- (*-------------------------------------------------------------------------*)
-
- PROCEDURE send_buff;
-
- VAR
- err_count : BYTE;
-
- BEGIN;
-
- (*---------------------------------------------------------------------*)
- (* Loop sending the same block until acked *)
- (*---------------------------------------------------------------------*)
-
- err_count := 10;
-
- REPEAT
-
- (*-------------------------------------------------------------------*)
- (* If too many errors then abort *)
- (*-------------------------------------------------------------------*)
-
- IF err_count = 0 THEN
- BEGIN;
- send_abort;
- EXIT;
- END;
-
- DEC(err_count);
-
- (*-------------------------------------------------------------------*)
- (* Send the data *)
- (*-------------------------------------------------------------------*)
-
- send_tnc_data_ub (big_buff, b_size);
-
- IF debug THEN
- WRITELN('Block sent ', b_size);
-
- (*-------------------------------------------------------------------*)
- (* Get response *)
- (*-------------------------------------------------------------------*)
-
- get_a_block;
-
- (*-------------------------------------------------------------------*)
- (* Validate incoming data *)
- (*-------------------------------------------------------------------*)
-
- b := check_block(small_buff);
-
- IF debug THEN
- WRITELN('GOT BLOCK = ', block_type, ' OK = ', b);
-
- (*-------------------------------------------------------------------*)
- (* Handle cancel *)
- (*-------------------------------------------------------------------*)
-
- IF block_type = can THEN
- BEGIN;
- do_mess_local(message_bin_abort_in);
- abort_sw := TRUE;
- EXIT;
- END;
-
- (*-------------------------------------------------------------------*)
- (* Loop until done *)
- (*-------------------------------------------------------------------*)
-
- UNTIL b AND (block_type = ack);
-
- END; (*----- End sending of buffer --------------------------------------*)
-
- (*-------------------------------------------------------------------------*)
- (* Ready a header block *)
- (*-------------------------------------------------------------------------*)
-
- PROCEDURE prep_header;
- BEGIN;
-
- (*---------------------------------------------------------------------*)
- (* Header is block 0 and is 128 byte block *)
- (*---------------------------------------------------------------------*)
-
- block_no := 0;
-
- b_size := 1 + 1 + 1 + 128 + 1;
-
- FILLCHAR(big_buff^, b_size, 0);
-
- big_buff^.xy_type := soh;
- tail_ptr := @big_buff^.x_tail;
-
- END;
-
- (*-------------------------------------------------------------------------*)
- (* Main line starts here *)
- (*-------------------------------------------------------------------------*)
-
- BEGIN;
-
- (*-----------------------------------------------------------------------*)
- (* Send the terminate block if wanted *)
- (*-----------------------------------------------------------------------*)
-
- IF end_it THEN
- BEGIN;
-
- prep_header;
- prep_buff;
- send_buff;
-
- EXIT;
-
- END;
-
- (*-----------------------------------------------------------------------*)
- (* Open the block for read *)
- (*-----------------------------------------------------------------------*)
-
- FILEMODE := 0;
-
- RESET(data_file^,1);
- file_size := FILESIZE(data_file^);
- CLOSE(data_file^);
-
- RESET(data_file^,128);
-
- FILEMODE := 2;
-
- free_semaphore(semaphore_interrupts);
-
- IF debug THEN
- WRITELN('FILESIZE = ', file_size);
-
- (*-----------------------------------------------------------------------*)
- (* Wait proper response *)
- (*-----------------------------------------------------------------------*)
-
- err_count := 11;
-
- REPEAT
-
- IF err_count = 0 THEN
- BEGIN;
- send_abort;
- EXIT;
- END;
-
- DEC(err_count);
-
- get_a_block;
-
- block_type := small_buff^.xy_type;
-
- IF debug THEN
- WRITELN('GOT BLOCK = ', block_type);
-
- IF (to_sw AND (error_cnt = 0)) OR (block_type = can) THEN
- BEGIN;
- IF to_sw THEN
- do_mess(message_bin_time_out)
- ELSE
- do_mess(message_bin_abort_in);
- abort_sw := TRUE;
- EXIT;
- END;
-
- UNTIL (block_type = nak) OR (block_type = 'C');
-
- (*-----------------------------------------------------------------------*)
- (* Set CRC switch appropriately *)
- (*-----------------------------------------------------------------------*)
-
- IF block_type = nak THEN
- crc_sw := FALSE
- ELSE
- crc_sw := TRUE;
-
- IF debug THEN
- WRITELN('CRC = ', crc_sw);
-
- (*-----------------------------------------------------------------------*)
- (* Send header *)
- (*-----------------------------------------------------------------------*)
-
- IF ymodem_sw THEN
- BEGIN;
-
- (*-------------------------------------------------------------------*)
- (* Header is block 0 and is 128 byte block *)
- (*-------------------------------------------------------------------*)
-
- block_no := 0;
-
- b_size := 1 + 1 + 1 + 128 + 1;
-
- FILLCHAR(big_buff^, b_size, 0);
-
- big_buff^.xy_type := soh;
- tail_ptr := @big_buff^.x_tail;
-
- (*-------------------------------------------------------------------*)
- (* Put out file name *)
- (*-------------------------------------------------------------------*)
-
- FOR i := 1 TO LENGTH(search_arg) DO
- IF search_arg[i] = '\' THEN
- search_arg[i] := '/';
-
- MOVE(search_arg[1], big_buff^.x_b, LENGTH(search_arg));
-
- i := LENGTH(search_arg) + 2;
-
- (*-------------------------------------------------------------------*)
- (* Put out file size *)
- (*-------------------------------------------------------------------*)
-
- STR(file_size, s);
-
- MOVE(s[1], big_buff^.x_b[i], LENGTH(s));
-
- INC(i, LENGTH(s) + 2);
-
- (*-------------------------------------------------------------------*)
- (* Put out the buffer *)
- (*-------------------------------------------------------------------*)
-
- prep_buff;
-
- send_buff;
-
- IF active_tcb^.error_sw OR abort_sw THEN
- EXIT;
-
- END; (*----- End sending of header ------------------------------------*)
-
- (*-----------------------------------------------------------------------*)
- (* Loop sending the data *)
- (*-----------------------------------------------------------------------*)
-
- block_no := 1;
- curr_size := 0;
-
- REPEAT
-
- (*---------------------------------------------------------------------*)
- (* Select things based on max block size *)
- (*---------------------------------------------------------------------*)
-
- IF ymodem_sw AND ((file_size - curr_size) > 512) THEN
- BEGIN;
-
- (*-----------------------------------------------------------------*)
- (* 1024 byte block to be sent *)
- (*-----------------------------------------------------------------*)
-
- b_size := 1 + 1 + 1 + 1024 + 1;
- big_buff^.xy_type := stx;
- tail_ptr := @big_buff^.y_tail;
-
- FILLCHAR(big_buff^.y_b, 1024, eof);
-
- BLOCKREAD(data_file^, big_buff^.y_b, 8, i);
-
- INC(curr_size, 1024);
-
- END
- ELSE
- BEGIN;
-
- (*-----------------------------------------------------------------*)
- (* 128 byte block to be sent *)
- (*-----------------------------------------------------------------*)
-
- b_size := 1 + 1 + 1 + 128 + 1;
- big_buff^.xy_type := soh;
- tail_ptr := @big_buff^.x_tail;
-
- FILLCHAR(big_buff^.x_b, 128, eof);
-
- BLOCKREAD(data_file^, big_buff^.x_b, 1, i);
-
- INC(curr_size, 128);
-
- END;
-
- IF debug THEN
- WRITELN('SB = ', b_size);
-
- (*---------------------------------------------------------------------*)
- (* Send the buffer. Exit if we fail *)
- (*---------------------------------------------------------------------*)
-
- prep_buff;
- send_buff;
-
- IF active_tcb^.error_sw OR abort_sw THEN
- EXIT;
-
- (*---------------------------------------------------------------------*)
- (* Increment block number and wrap as needed *)
- (*---------------------------------------------------------------------*)
-
- show_size;
-
- (*---------------------------------------------------------------------*)
- (* Increment block number and wrap as needed *)
- (*---------------------------------------------------------------------*)
-
- IF block_no = 255 THEN
- block_no := 0
- ELSE
- INC(block_no);
-
- IF debug THEN
- WRITELN('NEXT BLK = ', block_no);
-
- (*---------------------------------------------------------------------*)
- (* Loop until file all sent *)
- (*---------------------------------------------------------------------*)
-
- UNTIL curr_size >= file_size;
-
- (*-----------------------------------------------------------------------*)
- (* File sent.. Send EOT *)
- (*-----------------------------------------------------------------------*)
-
- b_size := 1;
- big_buff^.xy_type := eot;
-
- send_buff;
-
- END;